package asynctask

import (
	"fmt"
	"github.com/pkg/errors"
	"scase.io/application-auto-scaling-service/pkg/common"
	"scase.io/application-auto-scaling-service/pkg/db"
	event "scase.io/application-auto-scaling-service/pkg/service/event"
	"scase.io/application-auto-scaling-service/pkg/taskmgmt"
	"scase.io/application-auto-scaling-service/pkg/utils/logger"
)

type EcsScaleInTask struct {
	TaskId             string
	GroupId            string
	ScaleInInstanceIds []string
	BaseTask
	event *event.EventService
}

func NewEcsScaleInTask(taskId, groupId string, scaleInInstanceIds []string) *EcsScaleInTask {
	return &EcsScaleInTask{
		TaskId:             taskId,
		GroupId:            groupId,
		ScaleInInstanceIds: scaleInInstanceIds,
	}
}

func (t *EcsScaleInTask) GetKey() string {
	return t.GroupId
}

// GetType get task type
func (t *EcsScaleInTask) GetType() string {
	return TaskTypeScaleIn
}

func (t *EcsScaleInTask) Run(log *logger.FMLogger) error {
	group, err := db.GetScalingGroupById("", t.GroupId)
	if err != nil {
		return err
	}

	t.event, err = event.NewEventService(group.ProjectId, nil, log)
	if err != nil {
		log.Error("new event service error:%+v", err)
		return err
	}

	// 1. 移出伸缩组，数据库取消关联，使用deleting标记已被移出的ecs
	if err := db.RemoveInstance(t.ScaleInInstanceIds); err != nil {
		log.Error("[e_scale_in] disassociate instance error:%+v", err)
		eveReq := t.event.BuildInstanceEventReq("[Scale-in] failed", group.Id, fmt.Sprintf("scale-in fleet [%s] failed with error:%+v", group.FleetId, err.Error()),
			fmt.Sprintf("fleet [%s] scale in %d instance failed", group.FleetId, len(t.ScaleInInstanceIds)), common.EventTraceStateIncident)
		t.event.RegisterEvent(eveReq, group.ProjectId, log)
		return err
	}
	if err := db.UpdateCurrentNumber(group.Id, log); err != nil {
		log.Error("[e_scale_in] update group [%s] current instance num error:%+v", group.Id, err)
	}
	// 2. 起任务
	for _, instanceId := range t.ScaleInInstanceIds {
		err := db.InsertDeleteVmAsyncTask(instanceId, t.GroupId, group.ProjectId)
		if err != nil {
			// 若该任务正在运行，不处理
			if errors.Is(err, common.ErrDeleteTaskAlreadyExists) {
				continue
			}
			log.Error("[e_scale_in] insert delete vm async task error:%+v", err)
			return err
		}
		taskmgmt.GetTaskMgmt().AddTask(NewDelVmTask(instanceId, group.ProjectId, t.GroupId))
	}
	eveReq := t.event.BuildInstanceEventReq(fmt.Sprintf("[Scale-in-%d-vm] success", len(t.ScaleInInstanceIds)), group.Id, fmt.Sprintf("scale-in fleet[%s] success, vmId:%s ", group.FleetId, t.ScaleInInstanceIds),
		fmt.Sprintf("fleet [%s] scale in %d instance success", group.FleetId, len(t.ScaleInInstanceIds)), common.EventTraceStateNormal)
	t.event.RegisterEvent(eveReq, group.ProjectId, log)

	log.Info("[e_scale_in] group [%s] scaling in success", t.GroupId)
	return db.TxRecordEcsGroupScalingTaskComplete(t.GroupId, t.TaskId)
}
